#ifndef _AMRWBDEC_H
#define _AMRWBDEC_H
#include "amrwbdata.h"
#include "libavutil/lfg.h"

#define AMR_USE_16BIT_TABLES
typedef struct {
	AMRWBFrame                             frame; ///< AMRWB parameters decoded from bitstream
	enum Mode                        fr_cur_mode; ///< mode index of current frame
	uint8_t                           fr_quality; ///< frame quality index (FQI)
	float                      isf_cur[LP_ORDER]; ///< working ISF vector from current frame
	float                   isf_q_past[LP_ORDER]; ///< quantized ISF vector of the previous frame
	float               isf_past_final[LP_ORDER]; ///< final processed ISF vector of the previous frame
	double                      isp[4][LP_ORDER]; ///< ISP vectors from current frame
	double               isp_sub4_past[LP_ORDER]; ///< ISP vector for the 4th subframe of the previous frame

	float                   lp_coef[4][LP_ORDER]; ///< Linear Prediction Coefficients from ISP vector

	uint8_t                       base_pitch_lag; ///< integer part of pitch lag for the next relative subframe
	uint8_t                        pitch_lag_int; ///< integer part of pitch lag of the previous subframe

	float excitation_buf[AMRWB_P_DELAY_MAX + LP_ORDER + 2 + AMRWB_SFR_SIZE]; ///< current excitation and all necessary excitation history
	float                            *excitation; ///< points to current excitation in excitation_buf[]

	float           pitch_vector[AMRWB_SFR_SIZE]; ///< adaptive codebook (pitch) vector for current subframe
	float           fixed_vector[AMRWB_SFR_SIZE]; ///< algebraic codebook (fixed) vector for current subframe

	float                    prediction_error[4]; ///< quantified prediction errors {20log10(^gamma_gc)} for previous four subframes
	float                          pitch_gain[6]; ///< quantified pitch gains for the current and previous five subframes
	float                          fixed_gain[2]; ///< quantified fixed gains for the current and previous subframes

	float                              tilt_coef; ///< {beta_1} related to the voicing of the previous subframe

	float                 prev_sparse_fixed_gain; ///< previous fixed gain; used by anti-sparseness to determine "onset"
	uint8_t                    prev_ir_filter_nr; ///< previous impulse response filter "impNr": 0 - strong, 1 - medium, 2 - none
	float                           prev_tr_gain; ///< previous initial gain used by noise enhancer for threshold

	float samples_az[LP_ORDER + AMRWB_SFR_SIZE];         ///< low-band samples and memory from synthesis at 12.8kHz
	float samples_up[UPS_MEM_SIZE + AMRWB_SFR_SIZE];     ///< low-band samples and memory processed for upsampling
	float samples_hb[LP_ORDER_16k + AMRWB_SFR_SIZE_16k]; ///< high-band samples and memory from synthesis at 16kHz

	float          hpf_31_mem[2], hpf_400_mem[2]; ///< previous values in the high pass filters
	float                           demph_mem[1]; ///< previous value in the de-emphasis filter
	float               bpf_6_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band band pass filter
	float                 lpf_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band low pass filter

	AVLFG                                   prng; ///< random number generator for white noise excitation
	uint8_t                          first_frame; ///< flag active during decoding of the first frame
} AMRWBContext;

static av_cold int amrwb_decode_init(AVCodecContext *avctx);
static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf);
static void decode_isf_indices_36b(uint16_t *ind, float *isf_q);
static void decode_isf_indices_46b(uint16_t *ind, float *isf_q);
static void isf_add_mean_and_past(float *isf_q, float *isf_past);
static void interpolate_isp(double isp_q[4][LP_ORDER], const double *isp4_past);
static void decode_pitch_lag_high(int *lag_int, int *lag_frac, int pitch_index,uint8_t *base_lag_int, int subframe);
static void decode_pitch_lag_low(int *lag_int, int *lag_frac, int pitch_index,uint8_t *base_lag_int, int subframe, enum Mode mode);
static void decode_pitch_vector(AMRWBContext *ctx,const AMRWBSubFrame *amr_subframe,const int subframe);
#define BIT_STR(x,lsb,len) (((x) >> (lsb)) & ((1 << (len)) - 1))

#define BIT_POS(x, p) (((x) >> (p)) & 1)

static inline void decode_1p_track(int *out, int code, int m, int off);
static inline void decode_2p_track(int *out, int code, int m, int off);
static void decode_3p_track(int *out, int code, int m, int off);
static void decode_4p_track(int *out, int code, int m, int off);
static void decode_5p_track(int *out, int code, int m, int off);
static void decode_6p_track(int *out, int code, int m, int off);
static void decode_fixed_vector(float *fixed_vector, const uint16_t *pulse_hi,const uint16_t *pulse_lo, const enum Mode mode);
static void decode_gains(const uint8_t vq_gain, const enum Mode mode,float *fixed_gain_factor, float *pitch_gain);
static void pitch_sharpening(AMRWBContext *ctx, float *fixed_vector);
static float voice_factor(float *p_vector, float p_gain,float *f_vector, float f_gain);
static float *anti_sparseness(AMRWBContext *ctx,float *fixed_vector, float *buf);
static float stability_factor(const float *isf, const float *isf_past);
static float noise_enhancer(float fixed_gain, float *prev_tr_gain,float voice_fac,  float stab_fac);
static void pitch_enhancer(float *fixed_vector, float voice_fac);
static void synthesis(AMRWBContext *ctx, float *lpc, float *excitation,float fixed_gain, const float *fixed_vector,float *samples);
static void de_emphasis(float *out, float *in, float m, float mem[1]);
static void upsample_5_4(float *out, const float *in, int o_size);
static float find_hb_gain(AMRWBContext *ctx, const float *synth,uint16_t hb_idx, uint8_t vad);
static void scaled_hb_excitation(AMRWBContext *ctx, float *hb_exc,const float *synth_exc, float hb_gain);
static float auto_correlation(float *diff_isf, float mean, int lag);
static void extrapolate_isf(float out[LP_ORDER_16k], float isf[LP_ORDER]);
static void lpc_weighting(float *out, const float *lpc, float gamma, int size);
static void hb_synthesis(AMRWBContext *ctx, int subframe, float *samples,const float *exc, const float *isf, const float *isf_past);
static void hb_fir_filter(float *out, const float fir_coef[HB_FIR_SIZE + 1],float mem[HB_FIR_SIZE], const float *in);
static void update_sub_state(AMRWBContext *ctx);
static int amrwb_decode_frame(AVCodecContext *avctx, void *data, int *data_size,AVPacket *avpkt);
#if CONFIG_SMALL
#   define NULL_IF_CONFIG_SMALL(x) NULL
#else
#   define NULL_IF_CONFIG_SMALL(x) x
#endif
AVSampleFormat tmp[2]={SAMPLE_FMT_FLT,SAMPLE_FMT_NONE};
AVCodec amrwb_decoder;
#undef NULL_IF_CONFIG_SMALL
//
//#include "libavutil/internal.h"
//AVCodec amrwb_decoder = {
//	"amrwb",
//	CODEC_TYPE_AUDIO,
//	CODEC_ID_AMR_WB,
//	sizeof(AMRWBContext),
//	amrwb_decode_init,0,0,
//	amrwb_decode_frame,0,0,0,0,0,
//	NULL_IF_CONFIG_SMALL("Adaptive Multi-Rate WideBand"),0,
//	tmp
//};
#endif